package com.sk.weichat.util;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.media.TimedMetaData;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.IntDef;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.TextureView;

import com.sk.weichat.MyApplication;
import com.sk.weichat.ui.base.CoreManager;

import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.Map;

import fm.jiecao.jcvideoplayer_lib.JCMediaManager;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Scheduler;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.ISurfaceTextureHolder;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
import tv.danmaku.ijk.media.player.misc.IAndroidIO;

import static android.media.AudioManager.STREAM_MUSIC;

/**
 * @author lzs
 * @date 2019/10/23
 * Email:343067508@qq.com
 **/
public final class MediaPlayerHelper implements IMediaPlayer.OnPreparedListener, IMediaPlayer.OnCompletionListener, IMediaPlayer.OnBufferingUpdateListener, IMediaPlayer.OnSeekCompleteListener, IMediaPlayer.OnErrorListener, IMediaPlayer.OnInfoListener, IMediaPlayer.OnVideoSizeChangedListener {
    private Handler mHandler;
    private IMediaPlayer mediaPlayer;
    private static final String TAG = "MediaPlayerHelper";

    public boolean ismEnableMediaCodec() {
        return mEnableMediaCodec;
    }

    public void setmEnableMediaCodec(boolean mEnableMediaCodec) {
        this.mEnableMediaCodec = mEnableMediaCodec;
    }

    private boolean mEnableMediaCodec;

    public String getCurrentUrl() {
        return currentUrl;
    }

    //当前播放的视频路径
    private String currentUrl = "";

    private MediaPlayerHelper() {
        mHandler = new Handler(Looper.getMainLooper());
    }

    public static final int state_unplay = 0;
    public static final int state_playing = 1;
    public static final int state_pause = 2;
    public static final int state_stop = 3;
    WeakReference<MediaPlayerListener> listenerRef;

    @Override
    public void onPrepared(IMediaPlayer mp) {
        if (listenerRef.get() != null) {
            listenerRef.get().onPrepared(mp);
        }
        //先静音
        mediaPlayer.setVolume(0, 0);
        long pos = getCurrentPosition(currentUrl);
        if (pos > 0) {
            Log.e(TAG, "seekto pos:" + pos);
            seekTo(pos);
        } else {
            Log.e(TAG, "start pos :" + pos);
            start();
        }
    }

    @Override
    public void onCompletion(IMediaPlayer mp) {
        if (listenerRef.get() != null) {
            listenerRef.get().onCompletion(mp);
        }
    }

    @Override
    public void onBufferingUpdate(IMediaPlayer mp, int percent) {
        if (listenerRef.get() != null) {
            listenerRef.get().onBufferingUpdate(mp, percent);
        }
    }

    @Override
    public void onSeekComplete(IMediaPlayer mp) {
        Log.e(TAG, "onSeekComplete");
        if (listenerRef.get() != null) {
            listenerRef.get().onSeekComplete(mp);
        }
        start();
    }

    @Override
    public boolean onError(IMediaPlayer mp, int what, int extra) {
        if (listenerRef.get() != null) {
            listenerRef.get().onError(mp, what, extra);
        }
        return false;
    }

    @Override
    public boolean onInfo(IMediaPlayer mp, int what, int extra) {
        if (listenerRef.get() != null) {
            listenerRef.get().onInfo(mp, what, extra);
        }
        return false;
    }

    @Override
    public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) {
        if (listenerRef.get() != null) {
            listenerRef.get().onVideoSizeChanged(mp, width, height);
        }
    }

    @IntDef({state_unplay, state_playing, state_pause, state_stop})
    @Retention(RetentionPolicy.SOURCE)
    @Target({
            ElementType.PARAMETER,
            ElementType.FIELD,
            ElementType.METHOD,
    })
    public @interface PlayerState {

    }

    @PlayerState
    private int state = state_unplay;

    public static MediaPlayerHelper getInstance() {
        return MediaPlayerHelper.SingletonHolder.instance;
    }

    public void setMediaPlayerHelperListener(MediaPlayerListener listener) {
//        if (listenerRef != null && listenerRef.get() != null) {
//            listenerRef.clear();
//        }
        listenerRef = new WeakReference<>(listener);
    }

    private static class SingletonHolder {
        static MediaPlayerHelper instance = new MediaPlayerHelper();
    }


    public void prepare(SurfaceTexture surfaceTexture, String url, boolean isLoop) throws IOException {
        currentUrl = url;
        Observable.create(new ObservableOnSubscribe<Object>() {

            @Override
            public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                //耗时
//                if (mediaPlayer != null) {
//                    mediaPlayer.release();
//                    mediaPlayer = null;
//                }
                if (mediaPlayer == null) {
                    mediaPlayer = createPlayer();
                }
                mediaPlayer.reset();
                mediaPlayer.setAudioStreamType(STREAM_MUSIC);
                //mediaPlayer.setVolume(getCurrentVolume(url), getCurrentVolume(url));
                mediaPlayer.setDataSource(url);
                mediaPlayer.setLooping(isLoop);
                mediaPlayer.setScreenOnWhilePlaying(true);
                mediaPlayer.setOnPreparedListener(MediaPlayerHelper.this);
                mediaPlayer.setOnCompletionListener(MediaPlayerHelper.this);
                mediaPlayer.setOnBufferingUpdateListener(MediaPlayerHelper.this);
                mediaPlayer.setScreenOnWhilePlaying(true);
                mediaPlayer.setOnSeekCompleteListener(MediaPlayerHelper.this);
                mediaPlayer.setOnErrorListener(MediaPlayerHelper.this);
                mediaPlayer.setOnInfoListener(MediaPlayerHelper.this);
                mediaPlayer.setOnVideoSizeChangedListener(MediaPlayerHelper.this);

                mediaPlayer.prepareAsync();
                if (surfaceTexture != null) {
                    mediaPlayer.setSurface(new Surface(surfaceTexture));
                }
                emitter.onNext("");
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Object>() {

            @Override
            public void accept(Object o) throws Exception {
                // Log.e("lzs", "accept");
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {

            }
        });

    }

    public void prepare(SurfaceHolder surfaceHolder, String url, boolean isLoop) throws IOException {
        currentUrl = url;
        Observable.create(new ObservableOnSubscribe<Object>() {

            @Override
            public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
                //耗时
                if (mediaPlayer != null) {
                    mediaPlayer.release();
                    mediaPlayer = null;
                }
                //if (mediaPlayer == null) {
                mediaPlayer = createPlayer();
                //}

                mediaPlayer.reset();
                mediaPlayer.setAudioStreamType(STREAM_MUSIC);
                //mediaPlayer.setVolume(getCurrentVolume(url), getCurrentVolume(url));
                mediaPlayer.setDataSource(url);
                mediaPlayer.setLooping(isLoop);
                mediaPlayer.setScreenOnWhilePlaying(true);
                mediaPlayer.setOnPreparedListener(MediaPlayerHelper.this);
                mediaPlayer.setOnCompletionListener(MediaPlayerHelper.this);
                mediaPlayer.setOnBufferingUpdateListener(MediaPlayerHelper.this);
                mediaPlayer.setScreenOnWhilePlaying(true);
                mediaPlayer.setOnSeekCompleteListener(MediaPlayerHelper.this);
                mediaPlayer.setOnErrorListener(MediaPlayerHelper.this);
                mediaPlayer.setOnInfoListener(MediaPlayerHelper.this);
                mediaPlayer.setOnVideoSizeChangedListener(MediaPlayerHelper.this);

                mediaPlayer.prepareAsync();
                if (surfaceHolder != null) {
                    mediaPlayer.setDisplay(surfaceHolder);
                }
                emitter.onNext("");
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Object>() {

            @Override
            public void accept(Object o) throws Exception {
                // Log.e("lzs", "accept");
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {

            }
        });

    }


    //创建一个新的player
    private IMediaPlayer createPlayer() {
        IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
        ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100L);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 10240L);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1L);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 1L);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1L);

        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 1);

        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);

        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "http-detect-range-support", 1);

        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "min-frames", 100);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);


//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);

        ijkMediaPlayer.setVolume(1.0f, 1.0f);

        ijkMediaPlayer.setOnMediaCodecSelectListener(new IjkMediaPlayer.OnMediaCodecSelectListener() {
            @Override
            public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level) {
                return null;
            }
        });
        setEnableMediaCodec(ijkMediaPlayer, mEnableMediaCodec);
        return ijkMediaPlayer;
    }

    //设置是否开启硬解码
    private void setEnableMediaCodec(IjkMediaPlayer ijkMediaPlayer, boolean isEnable) {
        int value = isEnable ? 1 : 0;
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", value);//开启硬解码
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", value);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", value);
    }

    public final void changeSurface(SurfaceTexture surfaceTexture) {
        if (surfaceTexture != null) {
            mediaPlayer.setSurface(new Surface(surfaceTexture));
        }
    }

    public final long getDuration() {
        if (mediaPlayer != null) {
            return mediaPlayer.getDuration();
        }
        return 0;
    }


    public final long getCurrentPosition() {
        if (mediaPlayer != null) {
            return mediaPlayer.getCurrentPosition();
        }
        return 0;
    }

    public final void release() {
        if (mediaPlayer == null) {
            return;
        }
        mediaPlayer.release();
    }

    public final void pause() {
        if (mediaPlayer == null) {
            return;
        }
        if (state == state_playing) {
            recordCurrentPosition(currentUrl);
        }
        mediaPlayer.pause();
        state = state_pause;
    }

    public final void stop() {
        if (mediaPlayer == null) {
            return;
        }
        if (state == state_playing) {

            recordCurrentPosition(currentUrl);
        }
        mediaPlayer.stop();
        state = state_stop;
    }

    public final void reset() {
        if (mediaPlayer == null) {
            return;
        }
        mediaPlayer.reset();
    }

    public final void start() {
        if (mediaPlayer == null) {
            return;
        }
        mediaPlayer.start();
        state = state_playing;
    }


    public final void onDestory() {
        if (mediaPlayer != null) {
            mediaPlayer.release();
        }
    }

    public final void seekTo(long position) {
        if (mediaPlayer != null) {
            mediaPlayer.seekTo(position);
        }
    }

    public @PlayerState
    int getPlayerState() {
        return state;
    }

    /**
     * 记录当前播放的进度
     *
     * @param url
     */
    private void recordCurrentPosition(String url) {
        String userID = CoreManager.getSelf(MyApplication.getInstance()).getUserId();
        PreferenceUtils.putLong(MyApplication.getInstance(), "pos_" + userID + "_" + url, mediaPlayer.getCurrentPosition());
    }

    private long getCurrentPosition(String url) {
        String userID = CoreManager.getSelf(MyApplication.getInstance()).getUserId();
        return PreferenceUtils.getLong(MyApplication.getInstance(), "pos_" + userID + "_" + url, mediaPlayer.getCurrentPosition());
    }

    /**
     * 记录当前视频的音量
     */
    public void recordCurrentVolume(String url, int volume) {
        String userID = CoreManager.getSelf(MyApplication.getInstance()).getUserId();
        PreferenceUtils.putInt(MyApplication.getInstance(), "volume_" + userID + "_" + url, volume);

    }

//    public int getCurrentVolume(String url) {
//        String userID = CoreManager.getSelf(MyApplication.getInstance()).getUserId();
//        return PreferenceUtils.getInt(MyApplication.getInstance(), "volume_" + userID + "_" + url, mediaPlayer.getCurrentPosition());
//    }

    public void recordSilent(String url, boolean isSilent) {
        String userID = CoreManager.getSelf(MyApplication.getInstance()).getUserId();
        PreferenceUtils.putBoolean(MyApplication.getInstance(), "silent_" + userID + "_" + url, isSilent);
    }

    public boolean getSilentRecord(String url) {
        String userID = CoreManager.getSelf(MyApplication.getInstance()).getUserId();
        return PreferenceUtils.getBoolean(MyApplication.getInstance(), "silent_" + userID + "_" + url, true);
    }

    /**
     *
     */
    public void playSilently(String url) {
        recordSilent(url, true);
        //静音播放
        setVolume(0);
    }

    /**
     * @param url
     */
    public void playUnSilent(String url) {
        recordSilent(url, false);
        setVolume(1.0f);
    }

    private void setVolume(float volume) {
        if (mediaPlayer != null) {
            mediaPlayer.setVolume(volume, volume);
        }
    }

    //视频居中播放
    public static void setVideoCenter(TextureView textureView, float viewWidth, float viewHeight, float videoWidth, float videoHeight) {

        Matrix matrix = new Matrix();
        float sx = viewWidth / videoWidth;
        float sy = viewHeight / videoHeight;
        float maxScale = Math.max(sx, sy);

        matrix.preTranslate((viewWidth - videoWidth) / 2, (viewHeight - videoHeight) / 2);
        matrix.preScale(videoWidth / viewWidth, videoHeight / viewHeight);
        matrix.postScale(maxScale, maxScale, viewWidth / 2, viewHeight / 2);

        textureView.setTransform(matrix);
        textureView.postInvalidate();
    }

    public interface MediaPlayerListener {
        boolean onInfo(IMediaPlayer mp, int what, int extra);

        void onVideoSizeChanged(IMediaPlayer mp, int width, int height);

        void onSeekComplete(IMediaPlayer mp);

        void onBufferingUpdate(IMediaPlayer mp, int percent);

        boolean onError(IMediaPlayer mp, int what, int extra);

        void onCompletion(IMediaPlayer mp);

        void onPrepared(IMediaPlayer mp);
    }


}
